home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Unix / maclayersunixend1.30.shar / 1.30 / protocol.c < prev    next >
C/C++ Source or Header  |  1993-06-17  |  37KB  |  1,357 lines

  1. /*             Copyright (C) 1989 by David W. Trissel 
  2.  *
  3.  *              Not derived from licensed software.
  4.  *
  5.  * Permission is granted to freely use, copy, modify, and redistribute
  6.  * this software, provided that no attempt is made to gain profit from it,
  7.  * the author is not construed to be liable for any results of using the
  8.  * software, alterations are clearly marked as such, and this notice is
  9.  * not modified.
  10.  *
  11.  */
  12.  
  13. #include    <stdio.h>
  14. #ifdef NeXT
  15. #include    <libc.h>
  16. #endif
  17. #include    <sys/types.h>
  18. #include    <signal.h>
  19. #include    <errno.h>
  20. #include    "layers.h"
  21.  
  22.                 /* protocol.c - BSD MacLayers protocol driver */
  23.  
  24. /*    This module handles all interaction with the Macintosh MacLayers
  25. **    program. Services provided are:
  26. **
  27. **        InitLink()    - initialize link to MacLayers
  28. **
  29. **        TopChannel() - return highest prority channel
  30. **
  31. **        SendNew()    - request new layer channel of MacLayers
  32. **
  33. **        SendTitle() - change window title to given string (NOT IMPLENTED YET)
  34. **
  35. **        SendDelete()- tell MacLayers indicated layer has died
  36. **
  37. **        SendQuit()    - order MacLayers to terminate layers mode
  38. **
  39. **        SendData()    - send output to indicated channel's window
  40. **
  41. **        SendReshape() - send Shape structure to MacLayers
  42. **
  43. **        ProcessStreamin() - data is ready to be processed from MacLayers
  44. **
  45. */
  46.  
  47. #define DUMPALL
  48. #undef    DUMPALL
  49.  
  50. /* C library calls */
  51. #ifndef NeXT
  52. unsigned alarm();                /* alarm system call */
  53. #endif
  54.  
  55. static int        Start_proto1();
  56. static int        Start_proto2();
  57. static int        Start_proto3();
  58. static int        Start_proto4();
  59. static int        Start_proto5();
  60. static int        Start_proto6();
  61. static int        Start_proto7();
  62. static int        Start_proto8();
  63. static int        GetData();
  64. static void        Packet();
  65. static void        Parse();
  66. static void        AwaitInput();
  67. static void        asciishape();
  68. static void        fill4();
  69. static void        fill2();
  70. static void        fill1();
  71. static int        parseshape();
  72. static unsigned    get4();
  73. static unsigned    get2();
  74. static unsigned    get1();
  75. static int        myscanf();
  76. static int        mygetchar();
  77. static void        myungetc();
  78. static void        myalarm();
  79. static void        dumptime();
  80.  
  81. static char        inbuff[IOSIZE];        /* input buffer from MacLayers */
  82. static char     *inpos;                /* current input position in buffer */
  83. static int        insize = 0;            /* characters left to process */
  84. static int        settimeout = 0;        /* alarm system call timeout value */
  85. static int        Outstream = -1;        /* current output stream channel */
  86. static int        Instream = -1;        /* current input stream channel */
  87. static int        Sevenbits = 0;        /* communication channel is 7 bits */
  88.  
  89. static struct Shape    SNshape;        /* SendNew() shape response */
  90. static int        SNresp = 0;            /* SendNew() reponse poll flag */
  91. static int        SNchan = 0;            /* SendNew() channel return */
  92. #define SN_WAITING    -1000            /* SendNew() waiting response value */
  93.  
  94. #define ATTRSIZE    15                /* size of window attribute string */
  95.  
  96. #define FLUSH    fflush(stdout)
  97.  
  98.  
  99.                 /* Initlink() - initialize link with MacLayers */
  100.  
  101. /* Returns:
  102. **                0 - linkup failed
  103. **                1 - linkup successful, Maclayers now in protocol mode
  104. */
  105.  
  106. int
  107. Initlink()
  108. {
  109.     int Outstream = -1;                /* no default stream yet [UNUSED] */
  110.     int    Instream = -1;                /* no default stream yet [UNUSED] */
  111.     int        num1, num2, num3;        /* scanf item result */
  112.     int        err;                    /* error code */
  113.     int        doversion = 0;            /* version swapping flag [UNUSED] */
  114.  
  115. #define WAITTIME    10                /* second wait response time */
  116. #define INITTIME    2                /* wait time after succesful startup */
  117.  
  118.  
  119. /*** This patch not yet tested or implemented. Sent to the MacLayers archive 
  120. **** as:
  121.  
  122.  This patch fixes the "Encode request not from host" bug that occurs when
  123.  running MacLayers 1.00 on a VaxStation 3100 and Ultrix 3.1d.
  124.  
  125.  I came across this patch rather accidentally, so take it with a grain of
  126.  NaCl.
  127.  
  128.    ifndef vax
  129.        /* we must non-buffer input since all input must be immediate 
  130.        setbuf(stdin, NULL);            /* non-buffer all input 
  131.    endif
  132.  
  133. Archive manager Peter Newton added the following comments:
  134.  
  135.       Don't have a VaxStation to try it one.  Many people have had problems 
  136.       with Ultrix on VaxStations.  We have been giving them uuencoded 
  137.       binaries made under BSD.
  138.  
  139. *****************/
  140.  
  141.     /* V1.1 Note: The latest BSD Sun system doesn't break reads from the
  142.     ** terminal during signals. It appears that System V does do this
  143.     ** as do earlier BSD systems. At this time no special hacks will
  144.     ** be installed in just to support Unix versions not doing the breaks.
  145.     ** Without alarm timeouts host layers will hang if inappropriate
  146.     ** responses are received during protocol startup. But this should
  147.     ** only happen when a user types the layers command when not running
  148.     ** MacLayers.
  149.     */
  150.  
  151.     /* we must non-buffer input since all input must be immediate */
  152.     setbuf(stdin, NULL);            /* non-buffer all input */
  153.  
  154.     /* Host layers after V1.00 can receive protocol level information.
  155.     ** Send our level as ESC <id>. Version 1.00 MacLayers will treat
  156.     ** this as an illegal vt-100 sequence and issue a beep. Later versions
  157.     ** accept our protocol level and return their own after receiving
  158.     ** our protocol startup sequence sent here.
  159.     */
  160.     DO DEBUG("write protocol level 2: ESC 2\n");
  161.     /* send our protocol level out */
  162.     if ((err=printf("\033%c", HOSTPROTOCOL + '0')) < 0)
  163.       { DO DEBUG(" printf() error code %d\n", err);
  164.         return ( 0 );                /* problem with stdout */
  165.       }
  166.     FLUSH;
  167.  
  168.     /* send intitial request for terminal type and version number */
  169.     DO DEBUG("write: ESC [ c\n");
  170.     fputs("\033[c", stdout);
  171.     FLUSH;                            /* force output buffer */
  172.  
  173.     /* Attempt to read "ESC [ ? 8 ; typedigits ; versiondigits c" 
  174.     ** MacLayers in layers mode will return 8 ; 1 c
  175.     ** MacLayers in startup mode returns    8 ; X c
  176.     **        were X is the protocol level
  177.     */
  178.     num1 = num2 = num3 = -1;        /* default to unsupplied values */
  179.     DO DEBUG(" doing first scanf\n");
  180.     (void) myalarm(WAITTIME);        /* set timeout */
  181.     (void) myscanf("\033[?%d;%d;%dc", &num1, &num2, &num3);
  182.     (void) myalarm(0);                /* cancel alarm */
  183.     DO DEBUG("read ESC [ ? %d ; %d; %d c\n", num1, num2, num3);
  184.     if (num1 != 8 || num2 != 10)
  185.         return ( 0 );                /* not correct response or layers term ID */
  186.  
  187.     DO DEBUG("Client Protocol %d, Host Protocol %d\n", num3, HOSTPROTOCOL);
  188.  
  189.     /* Terminal type was valid, now verify protocol number */
  190.     switch (num3)
  191.     { case 1:
  192.       case 2:
  193.       case 3:
  194.       case 4:
  195.       case 5:
  196.       case 6:
  197.         /* these are all valid levels */
  198.         break;                        /* break for valid levels */
  199.  
  200.       case 9:
  201.         num3 = 7;                    /* 9 represents level 7 */
  202.         break;
  203.  
  204.       case 0:
  205.         num3 = 8;                    /* 0 represents level 8 */
  206.         break;
  207.  
  208.       default:
  209.         /* invalid response */
  210.         return ( 0 );                /* incorrect protocol level */
  211.  
  212.     } /* client protocol level switch */
  213.  
  214.     Clientlevel = num3;                /* set client protocol level offered */
  215.  
  216.     /* final protocol level cannot be higher than our current support level */
  217.     if (num3 > HOSTPROTOCOL)
  218.       {    DO DEBUG("Protocol level forced down to host level\n");
  219.         num3 = HOSTPROTOCOL;        /* force back down to the host level */
  220.       }
  221.  
  222.     Protocollevel = num3;            /* set effective protocol level */
  223.  
  224.     /* execute proper startup protocol level routine */
  225.     switch (Protocollevel)
  226.     { case 1:
  227.         return ( Start_proto1() );    /* handle protocol 1 startup sequence */
  228.  
  229.       case 2:
  230.         return ( Start_proto2() );    /* handle protocol 2 startup sequence */
  231.  
  232.       case 3:
  233.         return ( Start_proto3() );    /* handle protocol 3 startup sequence */
  234.  
  235.       case 4:
  236.         return ( Start_proto4() );    /* handle protocol 4 startup sequence */
  237.  
  238.       case 5:
  239.         return ( Start_proto5() );    /* handle protocol 5 startup sequence */
  240.  
  241.       case 6:
  242.         return ( Start_proto6() );    /* handle protocol 6 startup sequence */
  243.  
  244.       case 7:
  245.         return ( Start_proto7() );    /* handle protocol 7 startup sequence */
  246.  
  247.       case 8:
  248.         return ( Start_proto8() );    /* handle protocol 8 startup sequence */
  249.  
  250.     }
  251.  
  252.     /* invalid - refuse startup */
  253.     return ( 0 );                    /* SHOULD NOT OCCUR */
  254.  
  255. } /* Initlink() */
  256.  
  257.  
  258.                     /* Start_proto1() - Protocol 1 startup sequence */
  259.  
  260. static int
  261. Start_proto1()
  262. {
  263.     int        num1;                    /* scanf item result */
  264.  
  265.     /* This is the original MacLayers protocol for V1.00 */
  266.  
  267.     /* ask terminal if ENC_ENABLE is to be forced */
  268.     DO DEBUG("write: ESC [ F\n");
  269.     (void) fputs("\033[F", stdout);
  270.     FLUSH;                            /* force output buffer */
  271.  
  272.     /* attempt to read "ESC [ flag F" (flag indicates ENC_ENABLE status) */
  273.     num1 = -1;                        /* default to invalid response */
  274.     myalarm(WAITTIME);                /* set timeout */
  275.     (void) myscanf("\033[%dF", &num1);
  276.     myalarm(0);                        /* cancel alarm */
  277.     DO DEBUG("read ESC [ %d F\n", num1);
  278.     if (num1 != 1 && num1 != 0)
  279.         return ( 0 );                /* something's wrong */
  280.     if (num1 == 1)
  281.         Sevenbits = 1;                /* we are processing 7-bit data */
  282.  
  283.     /* now startup packet mode in non ENC_ENABLE processing */
  284.     DO DEBUG("write: ESC [ 2 ; 0 v\n");
  285.     (void) fputs("\033[2;0v", stdout);        /* "ESC [ 2 ; 0 v" */
  286.     FLUSH;                            /* force output buffer */
  287.  
  288. #if 0
  289.     {    int    i,j;
  290.         for (i=0; i<20; i++)
  291.         {    j = mygetchar();
  292.             DO DEBUG("---- read 0x%lx == %c\n", j, j);
  293.         }
  294.         return (0 );
  295.     }
  296. #endif
  297. #if 0
  298.         /* We must reset buffer to reread this character. Note
  299.         ** this won't work for triggering reads by layers.c unless 
  300.         ** client is sending more than 1 character because the select()
  301.         ** system call is used.
  302.         */
  303.         /* ungetc(num1, stdin);        /* return character back for re-read */
  304.         myungetc(num1);                /* re-insert this character */
  305. #endif
  306. #if 0
  307.         insize = 1;                    /* preset buffer with one character */
  308.         inpos = inbuff;                /* setup buffer pointer */
  309.         inbuff[0] = num1;            /* setup to reread this character */
  310. #endif
  311.     Clientlevel = 1;             /* assume protocol is level 1 */
  312.  
  313.     /* we are now in packet mode */
  314.     sleep( INITTIME );                /* let Macintosh keep up with us */
  315.  
  316.     return ( 1 );                    /* return successful startup */
  317.  
  318. } /* Start_proto1() */
  319.  
  320.  
  321.                 /* Start_proto2() - Protocol 2 startup sequence */
  322.  
  323. static int
  324. Start_proto2()
  325. {
  326.     /* This is the second MacLayers protocol starting with V1.1 */
  327.  
  328.     /* we are now in packet mode */
  329.     sleep( INITTIME );                /* let Macintosh keep up with us */
  330.  
  331.     return ( 1 );                    /* return successful startup */
  332.  
  333. } /* Start_proto2() */
  334.  
  335.  
  336.  
  337.                 /* Start_proto3() - Protocol 3 startup sequence */
  338.  
  339. static int
  340. Start_proto3()
  341. {
  342.     /* not yet defined! */
  343.     return ( 0 );                    /* SHOULD NOT OCCUR */
  344.  
  345. } /* Start_proto3() */
  346.  
  347.  
  348.  
  349.                 /* Start_proto4() - Protocol 4 startup sequence */
  350.  
  351. static int
  352. Start_proto4()
  353. {
  354.     /* not yet defined! */
  355.     return ( 0 );                    /* SHOULD NOT OCCUR */
  356.  
  357. } /* Start_proto4() */
  358.  
  359.  
  360.  
  361.                 /* Start_proto5() - Protocol 5 startup sequence */
  362.  
  363. static int
  364. Start_proto5()
  365. {
  366.     /* not yet defined! */
  367.     return ( 0 );                    /* SHOULD NOT OCCUR */
  368.  
  369. } /* Start_proto5() */
  370.  
  371.  
  372.  
  373.                 /* Start_proto6() - Protocol 6 startup sequence */
  374.  
  375. static int
  376. Start_proto6()
  377. {
  378.     /* not yet defined! */
  379.     return ( 0 );                    /* SHOULD NOT OCCUR */
  380.  
  381. } /* Start_proto6() */
  382.  
  383.  
  384.  
  385.                 /* Start_proto7() - Protocol 7 startup sequence */
  386.  
  387. static int
  388. Start_proto7()
  389. {
  390.     /* not yet defined! */
  391.     return ( 0 );                    /* SHOULD NOT OCCUR */
  392.  
  393. } /* Start_proto7() */
  394.  
  395.  
  396.  
  397.                 /* Start_proto8() - Protocol 8 startup sequence */
  398.  
  399. static int
  400. Start_proto8()
  401. {
  402.     /* not yet defined! */
  403.     return ( 0 );                    /* SHOULD NOT OCCUR */
  404.  
  405. } /* Start_proto8() */
  406.  
  407.  
  408.             /* TopChannel() - return highest prority channel */
  409.  
  410. int
  411. TopChannel()
  412. {
  413.     return ( Instream );
  414.  
  415. } /* TopChannel() */
  416.  
  417.  
  418.     /*
  419.     ** WARNING: Most of the following functions may be recursively called
  420.     **            as control commands are processed from the input stream
  421.     */
  422.  
  423.  
  424.             /* ProcessStreamin() - MacLayers has input to process */
  425.  
  426. void
  427. ProcessStreamin()
  428. {
  429.     DO dumptime();
  430.     DO DEBUG("ProcessStreamin() insize %d\n", insize);
  431.  
  432.     GetData();                        /* read some */
  433.  
  434.     while (insize > 0)                /* while more data to process ... */
  435.         Parse();                    /* process next chuck of data */
  436.  
  437. } /* ProcessStreamin() */
  438.  
  439.  
  440.         /* SendNew() - request new layer channel from MacLayers */
  441.  
  442. /*    This command is unique in that it returns a response from MacLayers.
  443. **    To do this we continue processing the input stream until we get
  444. **    our return. (This leads to recursive conditions.) The variables
  445. **    'SNresp', 'SNshape' and 'SNchan' are set when our reply is received.
  446. */
  447. int
  448. SendNew(shape)
  449. struct Shape    *shape;                /* shape to use for new window */
  450. {
  451.     int            i;                    /* attribute count variable */
  452.     char        astring[ATTRSIZE];    /* copy of attribute string */
  453.  
  454.     DO dumptime();
  455.     DO DEBUG("SendNew() new layer requested: '~%cA'\n", '1'+ATTRSIZE);
  456.  
  457.     /* check for a recursive call */
  458.     if (SNresp == SN_WAITING)
  459.       {    DO DEBUG("return 0 - recursive call\n");
  460.         return ( 0 );                /* return failure */
  461.       }
  462.  
  463.     putchar(ESCAPE);                /* send start of control packet char */
  464.     putchar('1' + ATTRSIZE);        /* send command size */
  465.     putchar('A');                    /* send command */
  466.     asciishape(shape, astring);        /* convert shape to string */
  467.     for (i=0; i < ATTRSIZE; i++)
  468.         putchar(astring[i]);        /* send next attribute digit */
  469.     FLUSH;
  470.  
  471.     /* now stay here and process the input stream until we see our response */
  472. /**** THIS SHOULD BE ENHANCED TO TIMEOUT WITH GetData() AND REISSUE REQUEST */
  473.     SNresp = SN_WAITING;            /* indicate we are waiting a response */
  474.     while (SNresp == SN_WAITING)
  475.       { DO DEBUG(" while (SNresp %d == %d)\n", SNresp, SN_WAITING);
  476.         AwaitInput();                /* wait till input from MacLayers arrives */
  477.         ProcessStreamin();            /* process available input */
  478.       }
  479.  
  480.     if (SNresp == -1)                /* if Maclayers rejected request */
  481.         SNchan = 0;                    /* return failure channel of zero */
  482.     else
  483.         *shape = SNshape;            /* else update shape structure */
  484.  
  485.     DO DEBUG("SendNew() returning channel %d\n", SNchan);
  486.  
  487.     return ( SNchan );                /* return the indicated channel */
  488.  
  489. } /* SendNew() */
  490.  
  491.  
  492.             /* SendReshape() - send to shape to MacLayers */
  493.  
  494. void
  495. SendReshape(chan, shape)
  496. int                chan;                /* channel shape belongs to */
  497. struct Shape    *shape;                /* shape to use for new window */
  498. {
  499.     int            i;                    /* attribute count variable */
  500.     char        astring[ATTRSIZE];    /* copy of attribute string */
  501.  
  502.     DO dumptime();
  503.     DO DEBUG("SendReshape() reshape: '~%cA'\n", '2'+ATTRSIZE);
  504.  
  505.     if (chan <= 0 || chan > MAXPCHAN)
  506.       {    DO DEBUG("BAD CHANNEL!!!\n");
  507.         return;                        /* ignore request */
  508.       }
  509.  
  510.     putchar(ESCAPE);                /* send start of control packet char */
  511.     putchar('2' + ATTRSIZE);        /* send command size */
  512.     putchar('R');                    /* send command */
  513.     putchar(chan + '0');            /* send channel */
  514.     asciishape(shape, astring);        /* convert shape to string */
  515.     DO DEBUG("shape: %.*s\n", ATTRSIZE, astring);
  516.     for (i=0; i < ATTRSIZE; i++)
  517.         putchar(astring[i]);        /* send next attribute digit */
  518.     FLUSH;
  519.  
  520. } /* SendReshape() */
  521.  
  522.  
  523.             /* SendTitle() - set layer's window title */
  524.  
  525. void
  526. SendTitle(chan, buff, cnt)
  527. int            chan;                    /* layer window ID */
  528. char        *buff;                    /* new title string */
  529. int            cnt;                    /* count of title length */
  530. {
  531.     int        i;                        /* work variable */
  532.  
  533.     DO DEBUG("SendTitle(chan%d, len %d, '%.*s')\n", chan, cnt, cnt, buff);
  534.  
  535.     if (chan <= 0 || chan > MAXPCHAN)
  536.       {    DO DEBUG("BAD CHANNEL!!!\n");
  537.         return;                        /* ignore request */
  538.       }
  539.  
  540.     if (cnt < 0)
  541.       {    DO DEBUG("BAD COUNT!!!\n");
  542.         return;                        /* ignore request */
  543.       }
  544.  
  545.     /* for now chop title size to 29 chars since that's MacLayer's limit */
  546.     if (cnt > 29)
  547.         cnt = 29;                    /* due to packet size limit */
  548.  
  549.     /* we must guarantee that the size will not appear to be another ESCAPE */
  550.     if ('2' + cnt == ESCAPE)
  551.         cnt--;                        /* truncate to avoid ESCAPE ESCAPE */
  552.     
  553.     putchar(ESCAPE);                /* send start of control packet char */
  554.     putchar('2' + cnt);                /* send size of packet */
  555.     putchar('T');                    /* send command */
  556.     putchar(chan + '0');            /* send channel ID */
  557.     for (i=0; i<cnt; i++)
  558.         putchar(buff[i]);            /* send out title */
  559.     FLUSH;
  560.  
  561. } /* SendTitle() */
  562.  
  563.  
  564.             /* SendDelete() - tell Maclayers layer died */
  565.  
  566. void
  567. SendDelete(chan)
  568. int        chan;                        /* dead channel ID */
  569. {
  570.     DO DEBUG("SendDelete(%d) '~2D%d'\n", chan, chan);
  571.  
  572.     if (chan <= 0 || chan > MAXPCHAN) /* check channel ID */
  573.       {    DO DEBUG("BAD CHANNEL!!!\n");
  574.         return;                        /* ignore request */
  575.       }
  576.  
  577.     putchar(ESCAPE);                /* send control packet start char */
  578.     putchar('2');                    /* send command size */
  579.     putchar('D');                    /* send command character */
  580.     putchar(chan + '0');            /* channel ID in ascii */
  581.     FLUSH;
  582.  
  583. } /* SendDelete() */
  584.  
  585.  
  586.             /* SendQuit() - order MacLayers to end layers mode */
  587.  
  588. void
  589. SendQuit(chan)
  590. int        chan;                        /* dead channel ID */
  591. {
  592.     DO dumptime();
  593.     DO DEBUG("SendQuit() '~1E'\n");
  594.  
  595.     putchar(ESCAPE);                /* send control packet start char */
  596.     putchar('1');                    /* send command size */
  597.     putchar('E');                    /* send command */
  598.     FLUSH;
  599.  
  600. } /* SendQuit() */
  601.  
  602.  
  603.             /* SendData() - send output to layer's window */
  604.  
  605. void
  606. SendData(chan, buff, cnt)
  607. int            chan;                    /* layer window ID */
  608. unsigned char *buff;                /* new title string */
  609. int            cnt;                    /* count of title length */
  610. {
  611.     unsigned c;                        /* output character being sent */
  612.  
  613.     DO
  614.       {    int        dcnt;
  615.  
  616.         dumptime();
  617.         DEBUG("SendData(chan %d, len %d, '", chan, cnt, cnt, buff);
  618.         for (dcnt=0; dcnt<cnt; dcnt++)
  619.             DEBUG("%c", buff[dcnt]); /* dump each char so null doesn't stop */
  620.         DEBUG("')\n");
  621.       }
  622.  
  623.     if (chan <= 0 || chan > MAXPCHAN)
  624.       {    DO DEBUG("BAD CHANNEL!!!\n");
  625.         return;                        /* ignore request */
  626.       }
  627.  
  628.     /* if new output channel stream then prefix redirect command */
  629.     if (chan != Outstream)
  630.       {    DO DEBUG("Redirecting output to %d '~2O%d'\n", chan, chan);
  631.         putchar(ESCAPE);            /* start of command sequence */
  632.         putchar('2');                /* send command size */
  633.         putchar('O');                /* send command */
  634.         putchar(chan + '0');        /* put out channel in ASCII */
  635.         Outstream = chan;            /* new output stream set */
  636.       }
  637.  
  638.     /* transmit the buffer converting the ESCAPE sequence to double ESCAPE */
  639.     while (cnt--)
  640.       {    c = *buff++;                /* get next output character */
  641. #ifdef DUMPALL
  642.         DO DEBUG("outchar %c 0x%x\n", c, c);
  643. #endif
  644.         if (c == ESCAPE || c == (ESCAPE + 0x80))
  645.           {    putchar(c);                /* put it out twice */
  646. #ifdef DUMPALL
  647.             DO DEBUG(" Doubled Escape!\n");
  648. #endif
  649.           }
  650.         putchar(c);                    /* write character out */
  651.       }
  652.  
  653.     FLUSH;                            /* force out queued output characters */
  654.         
  655. } /* SendData() */
  656.  
  657.  
  658.             /* Parse() - process next chunk of input stream */
  659.  
  660. static void
  661. Parse()
  662. {
  663. #define    ST_NULL        0                /* not primed for next state yet */
  664. #define    ST_STREAM    1                /* processing default stream input */
  665. #define    ST_PKT        2                /* processing packet data */
  666.  
  667.     int        c;                        /* input character being processed */
  668.  
  669.     static    int state = ST_NULL;    /* current input state */
  670.     static    int psize = 0;            /* packet size */
  671.     static    int    rempsize = 0;        /* remembered packet size */
  672.     static    char pdata[MAXSTR];        /* area for packet data */
  673.     static    char *ppos;                /* packet read insert position */
  674.     static    int escapemode = 0;        /* processing escape character */
  675.     static    int    escapechar;            /* escape character being processed */
  676.     static    pchan = -1;                /* packet input stream channel */
  677.  
  678.     DO dumptime();
  679.     DO DEBUG("Parse() insize %d\n", insize);
  680.  
  681.     while (insize-- > 0)            /* while more data */
  682.       {    c = (*inpos++ & 0xFF);        /* get next character (don't sign extend) */
  683.         switch (state)                /* process according to state */
  684.         { case ST_NULL:                /* prepare for new packet */
  685.             DO DEBUG("ST_NULL\n");
  686.             psize = 0;                /* clear packet size */
  687.             ppos = pdata;            /* start fill at data position */
  688.             pchan = Instream;        /* packet channel is current input stream */
  689.             state = ST_STREAM;        /* default is stream processing */
  690.  
  691.           case ST_STREAM:
  692.             /* stream keyboard input for layer */
  693.             /* check for escape char with possible high bit on */
  694. #ifdef DUMPALL
  695.             DO DEBUG("ST_STREAM %x/%x '%c' esc %d insz %d\n",
  696.                         c, c & 0x7f, c & 0x7f, escapemode, insize);
  697. #endif
  698.             if (c == ESCAPE || c == (ESCAPE | 0x80))
  699.               {    if (escapemode && c == escapechar) /* previous was ESCAPE */
  700.                 /* this is really a single ESCAPE character */
  701.                     escapemode = 0;        /* back out of ESCAPE mode */
  702.                 else
  703.                     /* what do we do with back to back esc esc+0x80 ? */
  704.                   {    /* flag in escape mode */
  705.                     escapemode++;
  706.                     escapechar = c;        /* remember character used for escape */
  707.                     continue;            /* and continue scan */
  708.                   }
  709.               }
  710.             else
  711.             if (escapemode)
  712.               { /* this is the start of a control packet */
  713.                 if (psize)                /* if we have previous data packet */
  714.                     Packet(pchan, psize, pdata); /* finish up previous pkt */
  715.                 /* process packet size */
  716.                 psize = (c & 0x7f) - '0'; /* save size byte */
  717.                 if (psize <= 0 || psize > MAXSTR)
  718.                   {    /* bad size */
  719.                     DO DEBUG("Bad pkt size %d\n", psize);
  720.                     break;                /* trash this packet */
  721.                   }
  722.                 rempsize = psize;        /* remember this size for later */
  723. #if 0
  724.                 ptimo = rtimo;            /* start receive timeout */                
  725. #endif
  726.                 escapemode = 0;            /* escape mode now off */
  727.                 ppos = pdata;            /* initialize data store pointer */
  728.                 state = ST_PKT;            /* expect packet data next */
  729.                 continue;                /* continue scan */
  730.               }
  731.                   
  732.             /* process standard data output character for current stream */
  733.             
  734.             *ppos++ = c;                /* save next data character */
  735.                 
  736.             if (++psize >= MAXSTR)        /* if packet full ... */
  737.               {    Packet(pchan, psize, pdata); /* process this packet */
  738.                 break;                    /* end packet processing */
  739.               }                  
  740.             continue;                    /* continue scan */
  741.                                                 
  742.           case ST_PKT:
  743.             /* process next paket data byte */
  744.             *ppos++ = c & 0x7f;        /* store next data byte */
  745. #ifdef DUMPALL
  746.             DO DEBUG("ST_PKT: %x '%c' sz %d\n", c & 0x7f, c & 0x7f, psize);
  747. #endif
  748.             if (--psize != 0)
  749.                 continue;
  750. #if 0
  751.             if (crc((unsigned char *) &rpkt, rpkt.pkt.HEADER_DSIZE+2))
  752.                 STATS(Scrcerr);            /* communications error */
  753.             else
  754. #endif
  755.             Packet(0, rempsize, pdata); /* process it */
  756.                 
  757.             } /* end build packet switch */
  758.             
  759. #if 0
  760.         ptimo = 0;                        /* no more receive timeout */
  761. #endif
  762.         state = ST_NULL;                /* no more receive packet in progress */
  763.             
  764.       } /* end while (insize) */
  765.           
  766.     if (state == ST_STREAM && psize )    /* if we have some data ... */
  767.       {    Packet(Instream, psize, pdata); /* process this data */
  768. #if 0
  769.         ptimo = 0;                        /* no more receive timeout */
  770. #endif
  771.         state = ST_NULL;                /* no more receive packet in progress */
  772.       }
  773.  
  774. } /* Parse() */
  775.  
  776.  
  777.         /* Packet() - prcess next input data string or control packet */
  778. static void
  779. Packet(chan, size, buff)
  780. int            chan;                        /* channel (0 if control packet) */
  781. int            size;                        /* amount of data */
  782. char        *buff;                        /* pointer to packet data */
  783. {
  784.     static struct Shape shape;            /* Shape structure */
  785.  
  786.     DO dumptime();
  787.     DO DEBUG("Packet(chan %d, size %d, '%.*s')\n", chan, size, size, buff);
  788.  
  789.     /* verify channel */
  790.     if (chan < 0 || chan > MAXPCHAN)
  791.       {    DO DEBUG("BAD CHANNEL!!\n");
  792.         return;                            /* ignore bad channel */
  793.       }
  794.  
  795.     /* if data packet (chan>0) feed data to server */
  796.     if (chan > 0)
  797.       {    ReceiveData(chan, buff, size);
  798.         return;                            /* we are through */
  799.       }
  800.  
  801.     /* control packet (channel 0) */
  802.     chan = buff[1] - '0';                /* assume channel specified */
  803.     if (chan < 0 || chan > MAXPCHAN)    /* if invalid ... */
  804.         chan = 0;                        /* set to zero */
  805.  
  806.     switch (buff[0])
  807.     { case 'I':        /* redirect stream */
  808.         DO DEBUG("CMD 'I' redirect stream to %c\n", buff[1]);
  809.         if (size != 2)                    /* verify size */
  810.             break;                        /* break if bad */
  811.         if (chan == 0)                    /* verify channel */
  812.             break;                        /* break if bad */
  813.         Instream = chan;                /* new instream channel */
  814.         return;                            /* we are through */
  815.  
  816.       case 'A':        /* returned A_NEWLAYER packet */
  817.         DO DEBUG("CMD 'A' A_NEWLAYER response %c newchan %c SNresp %d\n",
  818.                     buff[2], buff[1], SNresp);
  819.         if (size != 3 + ATTRSIZE)
  820.             break;                        /* break if bad */
  821.  
  822.         /* if SendNew() not waiting for a response this is invalid */
  823.         if (SNresp != SN_WAITING)
  824.             break;                        /* break if bad */
  825.  
  826.         if (buff[2] == '1')                /* if response is "failed" ... */
  827.             SNresp = -1;                /* show -1 response */
  828.         else
  829.         if (buff[2] == '0')                /* if response is "success" ... */
  830.           {    if (chan == 0)                /* if invalid channel */
  831.                 break;                    /* break if bad */
  832.             /* build shape structure for SendNew() */
  833.             if (parseshape(&SNshape, &buff[3]) == -1)
  834.                 break;                    /* if invalid data then bad packet */
  835.             SNresp = 0;                    /* show good response */
  836.             SNchan = chan;                /* indicate channel returned */
  837.           }
  838.         else
  839.             break;                        /* break if bad */
  840.  
  841.         DO DEBUG("SNresp = %d, SNchan = %d\n", SNresp, SNchan);
  842.         return;                            /* we are through */
  843.         
  844.       case 'N':        /* new layer creation */
  845.         DO DEBUG("CMD 'N' new layer creation newchan %c\n", buff[1]);
  846.         if (size != 2 + ATTRSIZE)        /* verify size */
  847.             break;                        /* break if bad */
  848.         if (chan == 0)                    /* verify channel */
  849.             break;                        /* break if bad */
  850.         /* build shape structure */
  851.         if (parseshape(&shape, &buff[2]) == -1)
  852.             break;                        /* if invalid data then bad packet */
  853.         ReceiveNew(chan, &shape);        /* pass to server */
  854.         return;                            /* packet is done */
  855.  
  856.       case 'D':        /* deleted layer */
  857.         DO DEBUG("CMD 'D' deleted layer %c\n", buff[1]);
  858.         if (size != 2)                    /* verify size */
  859.             break;                        /* break if bad */
  860.         if (chan == 0)                    /* verify channel */
  861.             break;                        /* break if bad */
  862.         ReceiveDelete(chan);            /* pass on to server */
  863.         return;                            /* packet is done */
  864.  
  865.       case 'E':        /* exit - awaiting shutdown */
  866.         DO DEBUG("CMD 'E' exit MacLayers awaiting shutdown msg\n");
  867.         if (size != 1)                    /* verify size */
  868.             break;                        /* break if bad */
  869.         ReceiveQuit();                    /* pass to server */
  870.         /* NOT REACHED*/
  871.         return;                            /* ?? should never reach here */
  872.  
  873.       case 'R':        /* reshaped */
  874.         DO DEBUG("CMD 'R' reshape chan %c\n", buff[1]);
  875.  
  876.         if (size != 2 + ATTRSIZE)        /* verify size */
  877.             break;                        /* break if bad */
  878.  
  879.         if (chan == 0)                    /* verify channel */
  880.             break;                        /* break if bad */
  881.  
  882.         /* build shape structure */
  883.         if (parseshape(&shape, &buff[2]) == -1)
  884.             break;                        /* if invalid data then bad packet */
  885.  
  886.         ReceiveReshape(chan, &shape);     /* tell server about shape */
  887.         return;                            /* packet processed */
  888.  
  889.       case 'S':        /* signal */
  890.         DO DEBUG("CMD 'S' SIGNAL chan %c sig %c\n", buff[1], buff[2]);
  891.         if (size != 3)                    /* verify size */
  892.             break;                        /* break if bad */
  893.         if (chan == 0)
  894.             break;                        /* break if bad */
  895.  
  896.         if (buff[2] == '0')                /* if SIGINT */
  897.             size = SIGINT;                /* yes */
  898.         else
  899.         if (buff[2] == '1')                /* if SIGHUP */
  900.             size = SIGHUP;                /* yes */
  901.         else
  902.             break;                        /* invalid signal */
  903.             
  904.         ReceiveSignal(chan, size);        /* pass to server */
  905.         return;                            /* packet processed */
  906.  
  907.       default:
  908.         DO DEBUG("ILLEGAL CONTROL PACKET!!!\n");
  909.         return;                            /* ignore bad packet */
  910.  
  911.     } /* end command packet switch */
  912.  
  913.     /* switch falls out if bad size or channel for given command */
  914.     DO DEBUG("Invalid size or channel!!!\n");    /* dump error */
  915.     return;                                /* ignore packet */
  916.  
  917. } /* Packet() */
  918.  
  919.  
  920.             /* GetData() - read next input from MacLayers stream */
  921.  
  922. /*    The settimeout variable indicates if we return when nothing
  923. **    is read within a certain amount of seconds. The return code is:
  924. **
  925. **        0 - timeout occured and no data was read
  926. **
  927. **        1 - no timeout occured, data read
  928. */
  929. static int
  930. GetData()
  931. {
  932.     int        result;                    /* return from read() */
  933.     int        i;                        /* work counter */
  934.     char    *ptr;                    /* work pointer */
  935.  
  936.     DO dumptime();
  937.     DO DEBUG("GetData()\n");
  938.  
  939.     /* if buffer still has data simply return (SHOULD NOT OCCUR?) */
  940.     if (insize > 0)
  941.       {    DO DEBUG("early return insize %d\n", insize);
  942.         return ( 1 );                /* act as through data read */
  943.       }
  944.     inpos = inbuff;                    /* next get will start at beginning */
  945.     insize = 0;                        /* default insize back to zero */
  946.  
  947.     /* set timeout if we are to do so */
  948.     if (settimeout)
  949.       {    DO DEBUG("alarm(%d)\n", settimeout);
  950.         (void) alarm(settimeout);    /* set timeout in seconds */
  951.       }
  952.  
  953.     /* do the read from stdin */
  954.     result = read(0, inbuff, IOSIZE);
  955.  
  956.     /* if alarm was set cancel it now */
  957.     if (settimeout)
  958.       {    DO DEBUG("alarm(0)\n");
  959.         myalarm(0);            /* cancel alarm */
  960.       }
  961.  
  962.     /* check for timeout or error */
  963.     /* EWOULDBLOCK for no data avail -(but we should not see this) */
  964.     /* EINTR if signal stopped the read -(rare but could happen) */
  965.     if (result <= 0)
  966.       {    DO DEBUG(" ?? no data result %d\n", result);
  967.         return ( 0 );                /* return nothing read */
  968.       }
  969.  
  970.     /* return with fresh buffer data */
  971.     insize = result;
  972.  
  973.     /* if 7-bit communication channel then strip all high bits */
  974.     if (Sevenbits)
  975.       for (i=result,ptr = inbuff; i>0; --i)
  976.         *ptr++ &= 0x7f;                /* strip high bit */
  977.  
  978.     DO DEBUG("read %d bytes\n", insize);
  979.     return ( 1 );                    /* return OK code */
  980.  
  981. } /* GetData() */
  982.  
  983.  
  984.             /* AwaitInput() - wait for more input from MacLayers */
  985.  
  986. static void
  987. AwaitInput()
  988. {
  989.     int        r;                        /*  read descriptor bits */
  990.  
  991.     DO dumptime();
  992.     DO DEBUG("AwaitInput() insize %d\n", insize);
  993.  
  994.     /* if buffer has data then don't wait */
  995.     if (insize > 0)
  996.       {    DO DEBUG("Return early insize %d\n", insize);
  997.         return;
  998.       }
  999.  
  1000.     do
  1001.       {    r = 1<<0;                    /* wait for read from input device */
  1002.         if (select(32, (fd_set *) &r, (fd_set *) NULL, (fd_set *) NULL, 
  1003.                     (struct timeval *) NULL) == -1)    /* if problem waiting ... */
  1004.           {    if (errno != EINTR)            /* if not simply signal taken ... */
  1005.               {    /* SHOULD NOT OCCUR - shutdown layers */
  1006.                 DO DEBUG("AwaitInput: select error %d\n", errno);
  1007.                 printf("layers: AwaitInput: bad select %d\n", errno);
  1008.                 FQuit();                    /* shutdown layers */
  1009.                 /* NOT REACHED */
  1010.               }
  1011.           }
  1012.       } while ((r & 1<<0) == 0);
  1013.         
  1014. } /* AwaitInput() */
  1015.  
  1016.                 /* asciishape() - convert Shape structure to ASCII */
  1017. static void
  1018. asciishape(shape, loc)
  1019. struct Shape    *shape;                        /* Shape structure for channel */
  1020. char            *loc;                        /* location to start filling result */
  1021. {
  1022.     char        *origloc;                    /* (for debuggin) */
  1023.  
  1024.     origloc = loc;                            /* remember start of string */
  1025.     fill4(&loc, shape->worigh);                /* origin h */
  1026.     fill4(&loc, shape->worigv);                /* origin v */
  1027.     fill2(&loc, shape->wlines);                /* lines high */
  1028.     fill2(&loc, shape->wchars);                /* chars wide */
  1029.     fill1(&loc, shape->wfont);                /* font size */
  1030.     fill2(&loc, shape->wattr);                /* attributes */
  1031.  
  1032.     DO DEBUG("asciishape(): %.*s\n", ATTRSIZE, origloc);
  1033.  
  1034. } /* asciishape() */
  1035.  
  1036.  
  1037.                     /* fill4() - convert parameter to ASCII */
  1038.  
  1039. static void
  1040. fill4(loc, valu)
  1041. char        **loc;                            /* pointer to fill area pointer */
  1042. unsigned    valu;                            /* value to use */
  1043. {
  1044.     fill2(loc, valu>>8);                    /* fill high half word */
  1045.     fill2(loc, valu & 0xff);                /* fill low half word */
  1046.  
  1047. } /* fill4() */
  1048.  
  1049.  
  1050.                     /* fill2() - convert parameter to ASCII */
  1051.  
  1052. static void
  1053. fill2(loc, valu)
  1054. char        **loc;                            /* pointer to fill area pointer */
  1055. unsigned    valu;                            /* value to use */
  1056. {
  1057.     fill1(loc, valu>>4);                    /* fill high byte */
  1058.     fill1(loc, valu & 0xf);                    /* fill low byte */
  1059.     
  1060. } /* fill2() */
  1061.  
  1062.  
  1063.                     /* fill1() - convert parameter to ASCII */
  1064.  
  1065. static void
  1066. fill1(loc, valu)
  1067. char        **loc;                            /* pointer to fill area pointer */
  1068. unsigned    valu;                            /* value to use */
  1069. {
  1070.     *(*loc)++ = "0123456789ABCDEF"[valu & 0xf]; /* return hex value */
  1071.  
  1072. } /* fill1() */
  1073.  
  1074.  
  1075.             /* parseshape() - convert ASCII image to Shape structure */
  1076.                 
  1077. static int    Badconvert;                        /* indicates bad conversion */
  1078.  
  1079. static int
  1080. parseshape(shape, loc)
  1081. struct Shape    *shape;                        /* Shape structure for channel */
  1082. char            *loc;                        /* location to start parsing */
  1083. {
  1084.     Badconvert = 0;                            /* clear bad characters indicator */
  1085.     shape->worigh = get4(&loc);                /* origin h */
  1086.     shape->worigv = get4(&loc);                /* origin v */
  1087.     shape->wlines = get2(&loc);                /* lines high */
  1088.     shape->wchars = get2(&loc);                /* chars wide */
  1089.     shape->wfont = get1(&loc);                /* font size */
  1090.     shape->wattr = get2(&loc);                /* attributes */
  1091.  
  1092.     DO DEBUG("ParseShape(): origv %d, origh %d, lines %d, chars %d\n",
  1093.                 shape->worigv, shape->worigh, shape->wlines, shape->wchars);
  1094.     DO DEBUG("   font %d, attr 0x%x, badconv %d\n",
  1095.                     shape->wfont, shape->wattr, Badconvert);
  1096.  
  1097.     return ( Badconvert ? -1 : 0 );            /* return conversion code */
  1098.  
  1099. } /* parseshape() */
  1100.  
  1101.  
  1102.                     /* get4() - convert ASCII to parameter */
  1103.  
  1104. static unsigned
  1105. get4(loc)
  1106. char        **loc;                            /* pointer to fill area pointer */
  1107. {
  1108.     unsigned    hi;                            /* high portion */
  1109.     unsigned    low;                        /* low portion */
  1110.  
  1111.     hi = get2(loc);                            /* get high byte */
  1112.     low = get2(loc);                        /* get low byte */
  1113.  
  1114.     return ( (hi<<8) + low );                /* return word value */
  1115.  
  1116. } /* get4() */
  1117.  
  1118.  
  1119.                     /* get2() - convert ASCII to parameter */
  1120.  
  1121. static unsigned
  1122. get2(loc)
  1123. char        **loc;                            /* pointer to fill area pointer */
  1124. {
  1125.     unsigned    hi;                            /* high portion */
  1126.     unsigned    low;                        /* low portion */
  1127.  
  1128.     hi = get1(loc);                            /* get high half */
  1129.     low = get1(loc);                        /* get low half */
  1130.  
  1131.     return ( (hi<<4) + low );                /* return byte value */
  1132.     
  1133. } /* get2() */
  1134.  
  1135.  
  1136.                     /* get1() - convert ASCII to parameter */
  1137.  
  1138. /*    This function sets 'Badconvert' if an invalid character is detected */
  1139.  
  1140. static unsigned
  1141. get1(loc)
  1142. char        **loc;                            /* pointer to fill area pointer */
  1143. {
  1144.     int            c;                            /* character to convert */
  1145.     
  1146.     c = *(*loc)++;                            /* fetch character */
  1147.     
  1148.     if (c >= '0' && c <= '9')
  1149.         /* zero through nine */
  1150.         return ( c - '0' );                    /* return it's binary value */
  1151.     
  1152.     if (c >= 'a' && c <= 'f')
  1153.         /* lower case hex */
  1154.         return ( c - 'a' + 10);                /* return it's binary value */
  1155.         
  1156.     if (c >= 'A' && c <= 'F')
  1157.         /* upper case hex */
  1158.         return ( c - 'A' + 10);                /* return it's binary value */
  1159.         
  1160.     /* invalid digit! */
  1161.     Badconvert++;                            /* set bad character flag */
  1162.     return ( 0 );                            /* return a zero */
  1163.  
  1164. } /* get1() */
  1165.  
  1166.  
  1167.                     /* myscanf() - RAW mode scanf routine */
  1168.  
  1169. /**    This routine is required because once our terminal is set into RAW mode
  1170. ***    the standard scanf routine fails on 7-bit lines whenever a high bit
  1171. ***    occurs in an input character. Only the %d, %c and exact input character
  1172. ***    images are supported in the input format string. All value parameters 
  1173. *** must be integer data type for both %d and %c.
  1174. */
  1175.  
  1176. static int
  1177. myscanf(str, arg1, arg2, arg3)
  1178. unsigned char    *str;                    /* scanf input string */
  1179. int        *arg1,*arg2,*arg3;                /* integer input pointer arguments */
  1180. {
  1181.     int        numscan = 0;                /* items filled in */
  1182.     int        build;                        /* %d build integer value */
  1183.     int        c;                            /* integer input character */
  1184.  
  1185.     DO dumptime();
  1186.     DO DEBUG("myscanf(%s)\n", str);
  1187.  
  1188.     /* scan string processing formats */
  1189.     while (*str)
  1190.           switch (*str)
  1191.         { case EOF:
  1192.             /* Error: probably our alarm timed out */
  1193.             return ( numscan );
  1194.             /* NOT REACHED */
  1195.  
  1196.           case '%':
  1197.             /* format specifier */
  1198.             switch (*++str)
  1199.             { case 'c':
  1200.                 /* return next character as is */
  1201.                 if ((build=mygetchar()) == -1)
  1202.                     return ( numscan );    /* no input, return count */
  1203.                 break;
  1204.  
  1205.               case 'd':
  1206.                 /* build input decimal value */
  1207.                 build = 0;
  1208.                 while ((c=mygetchar()) >= '0' && c <= '9')
  1209.                   {    build = build * 10;        /* next base ten digit */
  1210.                     build += c - '0';        /* add this digit */
  1211.                   }
  1212.                 myungetc(c);                /* return character ending number */
  1213.                 break;
  1214.  
  1215.           default:
  1216.                 return ( numscan );        /* return if error */
  1217.                 /* NOT REACHED */
  1218.             }
  1219.  
  1220.             /* return value to correct input parameter */
  1221.             switch (numscan)
  1222.             { case 0:
  1223.                 *arg1 = build;
  1224.                 break;
  1225.  
  1226.               case 1:
  1227.                 *arg2 = build;
  1228.                 break;
  1229.  
  1230.               case 2:
  1231.                 *arg3 = build;
  1232.                 break;
  1233.  
  1234.               default:
  1235.                 /* SHOULD NOT OCCUR */
  1236.                 return ( numscan );
  1237.                 /* NOT REACHED */
  1238.             }
  1239.  
  1240.             numscan++;                    /* count items scanned */
  1241.             str++;                        /* bump scan string past 'd' */
  1242.             break;                        /* continue scan */
  1243.  
  1244.           default:
  1245.             /* input character must match exactly */
  1246.             c = mygetchar();
  1247.             if (c != *str)
  1248.                 return ( numscan );        /* return - we don't match string */
  1249.             str++;                        /* to next character */
  1250.  
  1251.         } /* end scan string char switch */
  1252.  
  1253.     /* return number of items scanned */
  1254.     return ( numscan );
  1255.  
  1256. } /* myscanf() */
  1257.  
  1258.  
  1259.             /* mygetchar() - get character stripped to 7 bits */
  1260.  
  1261. /* Return:  -1 if timeout
  1262. **            char stripped to 7 bits
  1263. */
  1264.  
  1265. static int
  1266. mygetchar()
  1267. {
  1268.     int        c;                            /* next input character */
  1269.     int        result;                        /* read return value */
  1270.  
  1271.     DO dumptime();
  1272.  
  1273.     /* if character still in buffer return it */
  1274.     if (insize > 0)
  1275.       {    insize--;                        /* count down */
  1276.         c = (*inpos++) & 0x7f;            /* fetch next char */
  1277.         DO DEBUG(" 0x%lx '%c' ", c, c);
  1278.         return ( c );                    /* return 7-bit character */
  1279.       }
  1280.  
  1281.     /* attempt to read the buffer */
  1282.     result = GetData();                    /* no timeout (caller may have set) */
  1283.  
  1284.     /* return -1 if timeout */
  1285.     if (result == 0)
  1286.       {    DO DEBUG(" mygetchar ret -1\n");
  1287.         return ( -1 );
  1288.       }
  1289.  
  1290.     return ( mygetchar() );                /* return next character */
  1291.  
  1292. #if 0
  1293.     c = getchar() & 0x7f;                /* insure 7-bit only */
  1294.  
  1295. DO DEBUG(" 0x%lx '%c' ", c, c);
  1296.     return ( c );
  1297. #endif
  1298.  
  1299. } /* mygetchar() */
  1300.  
  1301.  
  1302.                 /* myungetc() - unget a character */
  1303.  
  1304. /* Must only be called to return when a character was previously fetched */
  1305.  
  1306. static void
  1307. myungetc(c)
  1308. int        c;                                /* character to unget */
  1309. {
  1310.     DO dumptime();
  1311.     DO DEBUG("myungetc(x%lx/%c)\n", c, c);
  1312.  
  1313.     insize++;                            /* count back up by one */
  1314.     *--inpos = c;                        /* restore previous character */
  1315.  
  1316. } /* myungetc() */
  1317.  
  1318.  
  1319.                 /* myalarm() - setup alarm timeout for next read */
  1320.  
  1321. static void
  1322. myalarm(time)
  1323. int            time;                        /* time in seconds (or zero) */
  1324. {
  1325.     DO dumptime();
  1326.     DO DEBUG("myalarm(%d)\n", time);
  1327.     settimeout = time;                    /* set for next read */
  1328.  
  1329. } /* myalarm() */
  1330.  
  1331.                 /* dumptime() - print out time in seconds */
  1332.  
  1333. /* THIS MAY BE SYSTEM DEPENDENT SO IS BASED UPON DEBUG IFDEF */
  1334. #ifdef DUMPALL
  1335. #include <sys/types.h>
  1336. #include <sys/time.h>
  1337. #endif
  1338.  
  1339. static void
  1340. dumptime()
  1341. {
  1342. #ifdef DUMPALL
  1343.     time_t    seconds;
  1344.     static time_t    base;
  1345.  
  1346.     if (base == 0)
  1347.       {    seconds = 0;
  1348.         base = time(NULL);
  1349.       }
  1350.     else
  1351.         seconds = time(NULL) - base;
  1352.  
  1353.     DO DEBUG("[%3d] ", seconds);
  1354.     
  1355. #endif
  1356. } /* dumptime() */
  1357.